#pragma once
#include <iostream>
#include <pthread.h>
#include <functional>
#include <string.h>

using namespace std;

// 各个子线程调用
namespace ThreadNS
{
    typedef function<void *(void *)> func_t;
    class Thread
    {
    private:
        // 与线程池中static void *HandlerTask(void *args)方法作用一样
        static void *Start_Routine(void *args)
        {
            Thread *Ct = static_cast<Thread *>(args);
            return Ct->run(Ct->args_);
        }

    public:
        Thread()
        {
            const int num = 64;
            char buffer[num];
            sprintf(buffer, "thread - %d", threadnumber++);
            name_ = buffer;
        }

        // args指针为线程池的对象指针
        bool Start(func_t func, void *args)
        {
            func_ = func; // func中存放的是线程池中传进来的函数方法static void *HandlerTask(void *args)
            args_ = args;
            // 这里与线程池中道理一样
            //因为pthread_create是c语言的接口所以在传递函数指针得时候无法使用包装器function
            //所以只能先将包装器中函数收下然后再通过自己建立一个静态函数再调用函数内部执行方法
            //如果使用C++进行多线程编程就可以直接调用对应的func_了，不需要绕这么大一圈。
            pthread_create(&id_, nullptr, Start_Routine, this);        
        }

        void *run(void *args)
        {
            // 本质是通过线程池中的static void *HandlerTask(void *args)方法调用任务对象中的仿函数。
            return func_(args);
        }

        ~Thread()
        {
            // delete无法析构void*类型的指针，因为无指定类型，delete不清楚具体该类型的内存布局和对象大小。
            delete static_cast<Thread *>(args_);
        }

        int join(void **retval)
        {
            return pthread_join(id_, retval);
        }

        string Name() { return name_; }

    private:
        pthread_t id_;           // 线程id
        string name_;            // 线程名字
        func_t func_;            // 被执行函数（是线程池中的HandlerTask方法）
        void *args_;             // 储存的是（线程池传递过来的this指针）
        static int threadnumber; // 用来记录当前是第几个线程；
    };
    int Thread::threadnumber = 1;
}